/*******************************************************************************
 * + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +
 * |                                                                         |
 *    faint - The Face Annotation Interface
 * |  Copyright (C) 2007  Malte Mathiszig                                    |
 * 
 * |  This program is free software: you can redistribute it and/or modify   |
 *    it under the terms of the GNU General Public License as published by
 * |  the Free Software Foundation, either version 3 of the License, or      |
 *    (at your option) any later version.                                     
 * |                                                                         |
 *    This program is distributed in the hope that it will be useful,
 * |  but WITHOUT ANY WARRANTY; without even the implied warranty of         |
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * |  GNU General Public License for more details.                           |
 * 
 * |  You should have received a copy of the GNU General Public License      |
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * |                                                                         |
 * + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +
 *******************************************************************************/

package pl.matt.opencv.model;

import java.awt.Point;
import java.io.Serializable;


/**
 * TO dla OpenCV
 * 
 * @author mateusz
 *
 */
public class Region implements Serializable {
	
	private static final long serialVersionUID = 4670842002974016100L;
	
	// Main attributes
	private String image;
	private int x, y, width, height;
	private double angle;
	private boolean usedForTraining = true;

	private String cachedFile = null;
	
	public Region(int x, int y, int width, int height, double angle, String image){
		this.x = x;
		this.y = y;
		this.width = width;
		this.height = height;
		this.angle = angle;
		this.image = image;
	}
	
	
	public Region(int x, int y, int width, int height) {
		this(x, y, width, height, 0, null);
	}


	public String toString(){
		return "position = ["+x+","+y+"] | width = "+width+" | height = "+height+" | angle = "+angle+" | image = "+this.image;
	}
	
	public boolean equals(Object region){
		if (region == null) return false;
		Region that = (Region) region;
		return (this.image.equals(that.image) &&
				this.angle == that.angle &&
				this.height == that.height &&
				this.width == that.width &&
				this.x == that.x &&
				this.y == that.y);
	}
	
	//-------------------- Setter and Getter --------------//

	public String getImage() {
		return this.image;
	}
	
	public int getHeight() {
		return height;
	}

	public void setHeight(int height) {
		this.height = height;
	}

	public int getWidth() {
		return width;
	}

	public void setWidth(int width) {
		this.width = width;
	}

	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}
	
	public void setPosition(Point p){
		this.x = p.x;
		this.y = p.y;
	}

	public int getY() {
		return y;
	}

	public void setY(int y) {
		this.y = y;
	}
	
	public String getCachedFile() {
		return cachedFile;
	}

	public void setCachedFile(String cachedFile) {
		this.cachedFile = cachedFile;
	}


	public boolean isUsedForTraining() {
		return usedForTraining;
	}
	
	/**
	 * Checks if a given point on the image lays inside of the region
	 * @param point
	 * @return
	 */
	public boolean containsPoint(Point point){
		
		// set point relative to center of region
		int x = getX() - point.x;
		int y = getY() - point.y;
		
		// rotate point to region coords
		double angle = Math.toRadians(getAngle());
		double finalX = x * Math.cos(angle) + y * -Math.sin(angle);
		double finalY = x * Math.sin(angle) + y * Math.cos(angle);
		
		if (Math.abs(finalX) < getWidth()/2 && Math.abs(finalY) < getHeight()/2) {	
			return true;
		}
		
		return false;
	}


	public void setUsedForTraining(boolean usedForTraining) {
		this.usedForTraining = usedForTraining;
	}


	/**
	 * @return
	 */
	public double getAngle() {
		return this.angle;
	}


	/**
	 * @param newAngle
	 */
	public void setAngle(double newAngle) {
		this.angle = newAngle;		
	}


}
